import {computed, readonly, ref} from 'vue'
import type InputProps from "@/components/input/type/InputProps.ts";
import {normalizeValue} from "@/components/utils.ts";

/**
 * created by yangtong on 2025/6/16 下午11:02
 * <br />
 * 输入框校验逻辑
 */
export function useInputValidation(props: InputProps) {
    const errorMessage = ref('')

    // 内置校验规则
    const builtInRules = {
        // 基础规则
        required: {
            validate: (val: string) => val.trim() !== '' || '不能为空',
            description: '必填校验'
        },

        // 长度相关规则
        minLength: {
            validate: (val: string, param?: string) => {
                const min = param ? parseInt(param) : 1
                return val.length >= min || `至少需要${min}个字符`
            },
            description: '最小长度校验，使用方式: minLength:5'
        },

        maxLength: {
            validate: (val: string, param?: string) => {
                const max = param ? parseInt(param) : 100
                return val.length <= max || `最多只能${max}个字符`
            },
            description: '最大长度校验，使用方式: maxLength:20'
        },

        length: {
            validate: (val: string, param?: string) => {
                if (!param) return true
                const [min, max] = param.split(',').map(n => parseInt(n.trim()))
                if (val.length < min) return `至少需要${min}个字符`
                if (val.length > max) return `最多只能${max}个字符`
                return true
            },
            description: '长度范围校验，使用方式: length:3,20'
        },

        // 格式校验
        email: {
            validate: (val: string) => {
                const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
                return emailRegex.test(val) || '请输入正确的邮箱格式'
            },
            description: '邮箱格式校验'
        },

        phone: {
            validate: (val: string) => {
                const phoneRegex = /^1[3-9]\d{9}$/
                return phoneRegex.test(val) || '请输入正确的手机号'
            },
            description: '手机号格式校验'
        },

        url: {
            validate: (val: string) => {
                try {
                    new URL(val)
                    return true
                } catch {
                    return '请输入正确的URL格式'
                }
            },
            description: 'URL格式校验'
        },

        // 数字相关
        number: {
            validate: (val: string) => !isNaN(Number(val)) || '必须是数字',
            description: '数字格式校验'
        },

        integer: {
            validate: (val: string) => /^-?\d+$/.test(val) || '必须是整数',
            description: '整数格式校验'
        },

        positiveNumber: {
            validate: (val: string) => {
                const num = Number(val)
                return (!isNaN(num) && num > 0) || '必须是正数'
            },
            description: '正数校验'
        },

        min: {
            validate: (val: string, param?: string) => {
                const min = param ? parseFloat(param) : 0
                const num = Number(val)
                return (!isNaN(num) && num >= min) || `不能小于${min}`
            },
            description: '最小值校验，使用方式: min:0'
        },

        max: {
            validate: (val: string, param?: string) => {
                const max = param ? parseFloat(param) : 100
                const num = Number(val)
                return (!isNaN(num) && num <= max) || `不能大于${max}`
            },
            description: '最大值校验，使用方式: max:100'
        },

        range: {
            validate: (val: string, param?: string) => {
                if (!param) return true
                const [min, max] = param.split(',').map(n => parseFloat(n.trim()))
                const num = Number(val)
                if (isNaN(num)) return '必须是数字'
                if (num < min) return `不能小于${min}`
                if (num > max) return `不能大于${max}`
                return true
            },
            description: '数值范围校验，使用方式: range:1,100'
        },

        // 字符类型
        alpha: {
            validate: (val: string) => /^[a-zA-Z]+$/.test(val) || '只能包含字母',
            description: '纯字母校验'
        },

        alphaNum: {
            validate: (val: string) => /^[a-zA-Z0-9]+$/.test(val) || '只能包含字母和数字',
            description: '字母数字校验'
        },

        alphaNumChinese: {
            validate: (val: string) => /^[a-zA-Z0-9\u4e00-\u9fa5]+$/.test(val) || '只能包含字母、数字和中文',
            description: '字母数字中文校验'
        },

        chinese: {
            validate: (val: string) => /^[\u4e00-\u9fa5]+$/.test(val) || '只能包含中文字符',
            description: '纯中文校验'
        },

        // 密码强度
        passwordWeak: {
            validate: (val: string) => val.length >= 6 || '密码至少6位',
            description: '弱密码校验（至少6位）'
        },

        passwordMedium: {
            validate: (val: string) => {
                if (val.length < 8) return '密码至少8位'
                if (!/[a-z]/.test(val)) return '必须包含小写字母'
                if (!/[A-Z]/.test(val)) return '必须包含大写字母'
                if (!/\d/.test(val)) return '必须包含数字'
                return true
            },
            description: '中等密码校验（8位，包含大小写字母和数字）'
        },

        passwordStrong: {
            validate: (val: string) => {
                if (val.length < 8) return '密码至少8位'
                if (!/[a-z]/.test(val)) return '必须包含小写字母'
                if (!/[A-Z]/.test(val)) return '必须包含大写字母'
                if (!/\d/.test(val)) return '必须包含数字'
                if (!/[!@#$%^&*(),.?":{}|<>]/.test(val)) return '必须包含特殊字符'
                return true
            },
            description: '强密码校验（8位，包含大小写字母、数字和特殊字符）'
        },

        // 证件号码
        idCard: {
            validate: (val: string) => {
                const idCardRegex = /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/
                return idCardRegex.test(val) || '请输入正确的身份证号'
            },
            description: '身份证号校验'
        },

        bankCard: {
            validate: (val: string) => {
                const bankCardRegex = /^[1-9]\d{12,18}$/
                return bankCardRegex.test(val) || '请输入正确的银行卡号'
            },
            description: '银行卡号校验'
        },

        // 特殊格式
        ip: {
            validate: (val: string) => {
                const ipRegex = /^(\d{1,3}\.){3}\d{1,3}$/
                if (!ipRegex.test(val)) return '请输入正确的IP地址'

                const parts = val.split('.')
                for (const part of parts) {
                    const num = parseInt(part)
                    if (num < 0 || num > 255) return '请输入正确的IP地址'
                }
                return true
            },
            description: 'IP地址校验'
        },

        domain: {
            validate: (val: string) => {
                const domainRegex = /^[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(\.[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/
                return domainRegex.test(val) || '请输入正确的域名'
            },
            description: '域名格式校验'
        },

        // 自定义正则
        pattern: {
            validate: (val: string, param?: string) => {
                if (!param) return true
                try {
                    const [regexStr, message] = param.split('|')
                    const regex = new RegExp(regexStr)
                    return regex.test(val) || (message || '格式不正确')
                } catch {
                    return true
                }
            },
            description: '自定义正则校验，使用方式: pattern:^[A-Z]|必须以大写字母开头'
        }
    }

    //正确解析规则字符串
    const parseRuleString = (ruleString: string): { name: string; param?: string } => {
        const colonIndex = ruleString.indexOf(':')
        if (colonIndex === -1) {
            return {name: ruleString}
        }

        return {
            name: ruleString.substring(0, colonIndex),
            param: ruleString.substring(colonIndex + 1)
        }
    }

    //使用计算属性生成规则函数数组
    const generatedBuiltInRules = computed(() => {
        if (!props.useRules || props.useRules.length === 0) {
            return []
        }

        const rules: ((val: string) => true | string)[] = []

        for (const ruleString of props.useRules) {
            const {name, param} = parseRuleString(ruleString)

            if (builtInRules[name as keyof typeof builtInRules]) {
                const rule = builtInRules[name as keyof typeof builtInRules]
                //生成正确的校验函数
                rules.push((val: string) => rule.validate(val, param))
            } else {
                console.warn(`未知的内置校验规则: ${name}`)
            }
        }

        return rules
    })

    // 合并所有规则
    const allRules = computed(() => {
        const rules: ((val: string) => true | string)[] = []

        // 检查是否已经在 useRules 中包含了 required
        const hasRequiredInUseRules = props.useRules?.includes('required') || false

        // 非空校验：优先使用 useRules 中的 required，其次使用 props.required
        if (props.required && !hasRequiredInUseRules) {
            rules.push(builtInRules.required.validate)
        }

        // 添加内置规则
        rules.push(...generatedBuiltInRules.value)

        // 添加自定义规则
        if (props.rules) {
            rules.push(...props.rules)
        }

        return rules
    })

    // 更新校验逻辑
    const validate = (): boolean => {
        errorMessage.value = ''

        const value = normalizeValue(props.modelValue)

        // 执行所有规则（包括内置的 required 规则）
        for (const rule of allRules.value) {
            const result = rule(value)
            if (result !== true) {
                errorMessage.value = result
                console.error(`${props.label}【${props.modelValue}】校验未通过：${result}`)
                return false
            }
        }

        return true
    }

    // 清除错误信息
    const clearError = () => {
        errorMessage.value = ''
    }

    // 获取所有错误信息（可选功能）
    const getAllErrors = (): string[] => {
        const errors: string[] = []
        const value = normalizeValue(props.modelValue)

        for (const rule of allRules.value) {
            const result = rule(value)
            if (result !== true) {
                errors.push(result)
            }
        }

        return errors
    }

    // 获取可用规则列表（调试用）
    const getAvailableRules = () => {
        return Object.keys(builtInRules).map(name => ({
            name,
            description: builtInRules[name as keyof typeof builtInRules].description
        }))
    }

    return {
        errorMessage,
        validate,
        getAllErrors,
        clearError,
        getAvailableRules,
        allRules: readonly(allRules)
    }
}